/**
* This file is part of ObjectFabric (http://objectfabric.org).
*
* ObjectFabric is licensed under the Apache License, Version 2.0, the terms
* of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
*
* Copyright ObjectFabric Inc.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.objectfabric;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.typedarrays.client.Uint8ArrayNative;
import com.google.gwt.typedarrays.shared.ArrayBuffer;
final class IndexedDBQueue extends BlockQueue implements Runnable {
private static final int MAX_ONGOING = 10;
private final IndexedDB _location;
private int _ongoing;
IndexedDBQueue(IndexedDB location) {
_location = location;
onStarted();
}
@Override
protected void enqueue() {
Platform.get().execute(this);
}
@Override
public void run() {
if (onRunStarting()) {
if (Debug.ENABLED)
ThreadAssert.resume(this, false);
runMessages(false);
while (_ongoing < MAX_ONGOING) {
Block block = nextBlock();
if (block == null)
break;
if (Debug.PERSISTENCE_LOG)
Log.write("IndexedDB write " + block.URI + " - " + Tick.toString(block.Tick));
if (Stats.ENABLED)
Stats.Instance.BlockWriteCount.incrementAndGet();
write(_location.transaction(false), block.URI, block.Tick, block.Buffs, block.Removals, true);
}
if (Debug.ENABLED)
ThreadAssert.suspend(this);
onRunEnded(false);
}
}
final void write(JavaScriptObject transaction, URI uri, long tick, Buff[] buffs, long[] removals, boolean callback) {
IndexedDBView view = (IndexedDBView) uri.getOrCreate(_location);
ArrayBuffer buffer=null;
if (buffs.length == 1) {
GWTBuff buff = (GWTBuff) buffs[0];
// buffer = buff.slice();
} else {
int capacity = 0;
for (int i = 0; i < buffs.length; i++)
capacity += buffs[i].remaining();
Uint8Array array = ((GWTPlatform) Platform.get()).newUint8Array(capacity);
int position = 0;
for (int i = 0; i < buffs.length; i++) {
GWTBuff buff = (GWTBuff) buffs[i];
array.set(buff.subarray(), position);
position += buff.remaining();
}
// buffer = array.buffer();
}
JavaScriptObject request = write(transaction, IndexedDB.BLOCKS, view.getKey(tick), buffer);
if (callback)
callback(request, view, uri, new long[] { tick }, buffs, removals);
if (removals != null)
for (int i = 0; i < removals.length; i++)
if (!Tick.isNull(removals[i]))
delete(_location.db(), IndexedDB.BLOCKS, view.getKey(removals[i]));
_ongoing++;
}
private native JavaScriptObject write(JavaScriptObject transaction, String store, String key, ArrayBuffer value) /*-{
return transaction.objectStore(store).put(value, key);
}-*/;
private native void callback(JavaScriptObject request, IndexedDBView view, URI uri, long[] tick, Buff[] buffs, long[] removals) /*-{
var this_ = this;
request.onsuccess = function(e) {
this_.@org.objectfabric.IndexedDBQueue::onsuccess(Lorg/objectfabric/IndexedDBView;Lorg/objectfabric/URI;[J[Lorg/objectfabric/Buff;[J)(view, uri, tick , buffs, removals);
};
}-*/;
private final void onsuccess(IndexedDBView view, URI uri, long[] tick, Buff[] buffs, long[] removals) {
_ongoing--;
for (int i = 0; i < buffs.length; i++)
buffs[i].recycle();
uri.onAck(view, tick[0]);
view.add(tick[0], removals);
// In case blocks left in queue
requestRun();
}
private native void delete(JavaScriptObject db, String store, String key) /*-{
var transaction = db.transaction(store, "readwrite");
transaction.objectStore(store)["delete"](key);
}-*/;
}